package com.seek.service.imp;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.seek.cache.CacheUtil;
import com.seek.common.handler.SpringContextHolder;
import com.seek.core.BaseServiceImpl;
import com.seek.dao.CustomerDao;
import com.seek.inter.interdto.InterDtoCUser;
import com.seek.model.entity.TCustomer;
import com.seek.service.CompanyAgentMoneyService;
import com.seek.service.CustomerService;
import com.seek.service.InterService;
import com.seek.util.CommonUtil;
import com.seek.util.Push2SingleUtil;

@Repository("customerService")
public class CustomerServiceImpl extends BaseServiceImpl<TCustomer> implements CustomerService {

	private InterService interService = (InterService) SpringContextHolder.getBean("interService");
	private CompanyAgentMoneyService companyAgentMoneyService = (CompanyAgentMoneyService) SpringContextHolder
			.getBean("companyAgentMoneyService");
	private Push2SingleUtil push2SingleUtil = (Push2SingleUtil) SpringContextHolder.getBean("push2SingleUtil");

	@Autowired
	public void setDao(CustomerDao customerDao) {
		super.setDao(customerDao);
	}

	public CustomerDao getDao() {
		return (CustomerDao) super.getDao();
	}

	public Map<String, Object> getBaseCustomerInfo(String companyId, String phoneNo) throws Exception {
		StringBuffer sb = new StringBuffer("");
		sb.append(
				"select a.id custId,a.phone_no phoneNo,a.headimg_url headimgUrl,a.card_number custNumber,a.name custName,a.status status,")
				.append("a.certification_status certificationStatus,a.card_bind_status cardBindStatus,a.addrbook_status addrbookStatus,(case when a.authed_date is not null then 1 else 0 end) oldStatus,")
				.append("a.mobile_status mobileStatus,a.zfb_status zfbStatus,a.has_elinkman hasElinkman,a.is_black isBlack,(case when a.status<>2 then 100000 else a.authed_credit end) authedCredit,a.active_date activeDate,a.password,")
				.append("(select ifnull(sum(b.req_money),0) from t_loan b where b.loan_status in (0,2,3,4,6) and b.customer_id=a.id) usedCredit,a.agent_id agentId,a.sub_agent_id subAgentId")
				.append(" from t_customer a where a.company_id=? and a.phone_no=?");
		Map<String, Object> ret = interService.findOneMapBySql(sb.toString(), new Object[] { companyId, phoneNo });
		// 再取得客户的银行卡信息
		if (ret != null && ret.keySet().size() > 0) {
			String sql = "select a.bank_name bankName,a.card_number cardNumber from t_customer_card a where a.history=0 and a.audit_status=1 and a.customer_id="
					+ ret.get("custId");
			Map<String, Object> card = interService.findOneMapBySql(sql);
			if (card != null && card.keySet().size() > 0)
				ret.putAll(interService.findOneMapBySql(sql));
		}
		return ret;
	}

	public boolean checkPhoneExists(String phoneNo, String excludeId) throws Exception {
		if (CommonUtil.isEmpty(phoneNo)) {
			return false;
		}
		String sql = "select 1 from t_customer where phone_no='" + phoneNo + "'";
		if (!CommonUtil.isEmpty(excludeId)) {
			sql += " and id<>" + excludeId;
		}
		return this.getDao().findBySql(sql).size() > 0 ? true : false;
	}

	@Transactional
	public void activeCustomer(String custId, String clientid, String agentId, String subAgentId) throws Exception {
		if (CommonUtil.isEmpty(agentId)) {
			String updateSql = "update t_customer set last_login_time=now(),client_id=?,active_date=now() where id=?";
			this.getDao().executeUpdateSql(updateSql, new Object[] { clientid, custId });
			return;
		}

		int[] money = companyAgentMoneyService.getAgentMoneySetting(CommonUtil.getLongValue(agentId), CommonUtil.getLongValue(subAgentId), 1);
		if (money[0] == 0 && money[1] == 0) {
			String updateSql = "update t_customer set last_login_time=now(),client_id=?,active_date=now() where id=?";
			this.getDao().executeUpdateSql(updateSql, new Object[] { clientid, custId });
			return;
		}

		// 添加代理商佣金
		companyAgentMoneyService.addAgentMoneyLog(CommonUtil.getLongValue(agentId), CommonUtil.getLongValue(subAgentId), money[0], money[1], null, CommonUtil.getLongValue(custId), 1);
		
		// 更新客户表
		String updateSql = "update t_customer set last_login_time=now(),client_id=?,active_date=now(),agent_money=?,sub_agent_money=? where id=?";
		this.getDao().executeUpdateSql(updateSql, new Object[] { clientid, money[0], money[1], custId });
	}

	@Override
	public int updateAuthStatus(String column, Integer status, Integer oldStatus, Long custId, Long companyId)
			throws Exception {
		String updateSql = "update t_customer set " + column + " = ? where id = ? and company_id = ? and " + column
				+ " = ?";

		return this.getDao().executeUpdateSqlWithRetun(updateSql, new Object[] { status, custId, companyId, oldStatus });
	}

	@Transactional
	public void certifyAudit(Long custId, String userId, int auditStatus, String auditRemark) throws Exception {
		String sql = "update t_customer_certify set audit_time=now(),audit_id=?,audit_status=?,audit_remark=? where customer_id =?";
		this.getDao().executeUpdateSql(sql, new Object[] { userId, auditStatus, auditRemark, custId });
		// 同步更新到客户的实名认证中
		auditStatus = auditStatus + 1;
		sql = "update t_customer set certification_status=? where id=?";
		this.getDao().executeUpdateSql(sql, new Object[] { auditStatus, custId });
		// 刷新客户的缓存
		String custToken = CacheUtil.getRedisData("COUSTOMER_TOKEN_" + custId);
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("certificationStatus", auditStatus);
		CacheUtil.refreshCustRedis(custToken, m);
		// 消息推送
		if (!CommonUtil.isEmpty(custToken)){
			InterDtoCUser cust = CacheUtil.getCLoginCache(custToken);
			if (cust != null && !CommonUtil.isEmpty(cust.getClientid())){
				if (auditStatus == 2){
					push2SingleUtil.push2Single(Push2SingleUtil.TYPE_OF_CERTIFY_SUC, cust.getClientid());
				}else{
					push2SingleUtil.push2Single(Push2SingleUtil.TYPE_OF_CERTIFY_FAIL, cust.getClientid());
				}
			}
		}
	}

	@Transactional
	public void zfbAudit(Long custId, String userId, int auditStatus, String auditRemark, int zfbCredit)
			throws Exception {
		// 更新支付宝认证状态
		String sql = "update t_customer_zfb set audit_time=now(),audit_id=?,audit_status=?,audit_remark=?,zfb_credit=? where customer_id =? and lsbz=0";
		this.getDao().executeUpdateSql(sql, new Object[] { userId, auditStatus, auditRemark, zfbCredit, custId });
		// 同步更新到客户的实名认证中
		String custToken = CacheUtil.getRedisData("COUSTOMER_TOKEN_" + custId);
		Map<String, Object> m = new HashMap<String, Object>();
		int zfbStatus = auditStatus == 1 ? 2 :3; 
		InterDtoCUser cust = CacheUtil.getCLoginCache(custToken);
		if (auditStatus == 1) { // 支付宝认证通过，则所有的认证都完成
			// 根据zfb额度取得客户在本系统中的可放款额度
			int authCredit = getUserCredit(zfbCredit);
			sql = "update t_customer set zfb_status=?,status=2,authed_date=now(),authed_credit=? where id=?";
			this.getDao().executeUpdateSql(sql, new Object[] { zfbStatus, authCredit, custId });

			m.put("status", 2);
			m.put("zfbStatus", zfbStatus);
			m.put("authedCredit", authCredit);
			
			if (cust!= null && !CommonUtil.isEmpty(cust.getClientid())){
				push2SingleUtil.push2Single(Push2SingleUtil.TYPE_OF_ZFB_SUC, cust.getClientid());
			}
		} else {
			sql = "update t_customer set zfb_status=? where id=?";
			this.getDao().executeUpdateSql(sql, new Object[] { zfbStatus, custId });
			m.put("zfbStatus", zfbStatus);
			if (cust!= null && !CommonUtil.isEmpty(cust.getClientid())){
				if (auditStatus == 2)
					push2SingleUtil.push2Single(Push2SingleUtil.TYPE_OF_ZFB_FAIL, cust.getClientid());
				else
					push2SingleUtil.push2Single(Push2SingleUtil.TYPE_OF_ZFB_FAIL_END, cust.getClientid());
			}
		}
		CacheUtil.refreshCustRedis(custToken, m);
	}

	private int getUserCredit(int zfbCredit) {
		if (zfbCredit >= 1000 && zfbCredit <= 1099)
			return 80000;
		else if (zfbCredit >= 1100 && zfbCredit <= 1599)
			return 100000;
		else if (zfbCredit >= 1600 && zfbCredit <= 2099)
			return 150000;
		else if (zfbCredit >= 2100 && zfbCredit <= 3099)
			return 200000;
		else if (zfbCredit >= 3100 && zfbCredit <= 5000)
			return 250000;
		else if (zfbCredit > 5001)
			return 300000;
		return 0;
	}

	public void setCustBlack(Long custId, int status) throws Exception {
		// 更新支付宝认证状态
		String sql = "update t_customer set is_black=? where id=?";
		this.getDao().executeUpdateSql(sql, new Object[] { status, custId });
		// 同步更新到客户的实名认证中
		String custToken = CacheUtil.getRedisData("COUSTOMER_TOKEN_" + custId);
		Map<String, Object> m = new HashMap<String, Object>();
		m.put("isBlack", status);
		CacheUtil.refreshCustRedis(custToken, m);
	}

	@SuppressWarnings("unchecked")
	@Transactional
	public void reCertiyZfb() throws Exception {
		// 检索需要重新支付宝认证的客户并重置客户的支付宝认证状态
		String sql = "select id,client_id from t_customer a where a.last_loan_date<date_sub(date_sub(date_format(now(),'%y-%m-%d'),interval extract( day from now())-1 day),interval 2 month) and a.zfb_status=2";
		List<Map<String, Object>> maps = this.getDao().findMapBySql(sql);
		// 更新客户状态
		sql = "update t_customer set zfb_status=0,last_loan_date=null,status=1 where last_loan_date<date_sub(date_sub(date_format(now(),'%y-%m-%d'),interval extract( day from now())-1 day),interval 2 month) and zfb_status=2)";
		this.getDao().executeUpdateSql(sql);
		// 更新客户支付宝认证记录的数据为失效
		sql = "update t_customer a,t_customer_zfb b set b.lsbz=1 where a.id=b.customer_id and b.lsbz=0 and a.zfb_status=0 and a.status=1";
		this.getDao().executeUpdateSql(sql);

		// 清除这些人的登录token
		for (Map<String, Object> m : maps) {
			String oldToken = CacheUtil.getRedisData("COUSTOMER_TOKEN_" + m.get("id"));
			if (!CommonUtil.isEmpty(oldToken)) {
				CacheUtil.delRedisData(oldToken);
				CacheUtil.delRedisData("COUSTOMER_TOKEN_" + m.get("id"));
			}
		}
	}

	@SuppressWarnings("unchecked")
	@Transactional
	public void reCertiyMobile() throws Exception {
		// 检索需要重新运营商认证的客户并重置客户的运营商认证状态
		String sql = "select id,client_id from t_customer a where a.last_loan_date<date_sub(date_sub(date_format(now(),'%y-%m-%d'),interval extract( day from now())-1 day),interval 6 month) and a.mobile_status=2";
		List<Map<String, Object>> maps = this.getDao().findMapBySql(sql);

		// 更新客户状态
		sql = "update t_customer set mobile_status=0,addrbook_status=0,last_loan_date=null,status=1,zfb_status=0 where  last_loan_date<date_sub(date_sub(date_format(now(),'%y-%m-%d'),interval extract( day from now())-1 day),interval 6 month) and mobile_status=2)";
		this.getDao().executeUpdateSql(sql);
		// 更新客户支付宝认证记录的数据为失效
		sql = "update t_customer a,t_customer_zfb b set b.lsbz=1 where a.id=b.customer_id and b.lsbz=0 and a.zfb_status=0 and a.status=1";
		this.getDao().executeUpdateSql(sql);

		// 清除这些人的登录token
		for (Map<String, Object> m : maps) {
			String oldToken = CacheUtil.getRedisData("COUSTOMER_TOKEN_" + m.get("id"));
			if (!CommonUtil.isEmpty(oldToken)) {
				CacheUtil.delRedisData(oldToken);
				CacheUtil.delRedisData("COUSTOMER_TOKEN_" + m.get("id"));
			}
		}

	}
}